package Ide;
import filepack.HJFIlter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
import java.util.Vector;
import javax.swing.JFileChooser;
import javax.swing.table.DefaultTableModel;
import tpcompiladores.*;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Jojo
 */
public class IDE extends javax.swing.JFrame {

    /**
     * Creates new form IDE
     */
    
    
    
    public IDE() {
        initComponents();
        NumberedEditor editor = new NumberedEditor();
        code.setEditorKit(editor);
        defaultFilePath = System.getProperty("user.dir") + "/prueba.txt";
        loadDefaultCode();
        tabla = (DefaultTableModel) tokenTable.getModel();
        tablaSimModel = (DefaultTableModel) simbolTable.getModel();
        tokens = new Vector<Token>();
        sintacticStructures = new Vector<>();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        code = new javax.swing.JEditorPane();
        jToolBar1 = new javax.swing.JToolBar();
        bOpen2 = new javax.swing.JButton();
        bSave2 = new javax.swing.JButton();
        bCompile = new javax.swing.JButton();
        jTabbedPane1 = new javax.swing.JTabbedPane();
        jScrollPane1 = new javax.swing.JScrollPane();
        console = new javax.swing.JTextArea();
        jScrollPane3 = new javax.swing.JScrollPane();
        tokenTable = new javax.swing.JTable();
        jScrollPane4 = new javax.swing.JScrollPane();
        simbolTable = new javax.swing.JTable();
        jScrollPane5 = new javax.swing.JScrollPane();
        consoleSin = new javax.swing.JTextArea();
        jPanel2 = new javax.swing.JPanel();
        jScrollPane6 = new javax.swing.JScrollPane();
        polacaText = new javax.swing.JTextArea();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        bOpen = new javax.swing.JMenuItem();
        bSave = new javax.swing.JMenuItem();
        bExit = new javax.swing.JMenuItem();
        jMenu3 = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenuItem2 = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setBackground(new java.awt.Color(0, 51, 51));

        jPanel1.setBackground(new java.awt.Color(0, 51, 51));
        jPanel1.setPreferredSize(new java.awt.Dimension(800, 600));
        jPanel1.setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        jScrollPane2.setBackground(new java.awt.Color(0, 0, 0));
        jScrollPane2.setPreferredSize(new java.awt.Dimension(800, 202));

        code.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        code.setPreferredSize(new java.awt.Dimension(106, 200));
        code.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                codeMouseReleased(evt);
            }
        });
        jScrollPane2.setViewportView(code);

        jPanel1.add(jScrollPane2, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 70, 770, 320));

        jToolBar1.setBackground(new java.awt.Color(0, 51, 51));
        jToolBar1.setFloatable(false);
        jToolBar1.setRollover(true);

        bOpen2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Ide/Open.jpg"))); // NOI18N
        bOpen2.setToolTipText("");
        bOpen2.setFocusable(false);
        bOpen2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        bOpen2.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        bOpen2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bOpen2ActionPerformed(evt);
            }
        });
        jToolBar1.add(bOpen2);

        bSave2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Ide/Save.jpg"))); // NOI18N
        bSave2.setFocusable(false);
        bSave2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        bSave2.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        bSave2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bSave2ActionPerformed(evt);
            }
        });
        jToolBar1.add(bSave2);

        bCompile.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Ide/Play.jpg"))); // NOI18N
        bCompile.setFocusable(false);
        bCompile.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        bCompile.setPreferredSize(new java.awt.Dimension(59, 58));
        bCompile.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        bCompile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bCompileActionPerformed(evt);
            }
        });
        jToolBar1.add(bCompile);

        jPanel1.add(jToolBar1, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 0, 770, 70));

        console.setColumns(20);
        console.setEditable(false);
        console.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        console.setRows(5);
        jScrollPane1.setViewportView(console);

        jTabbedPane1.addTab("Console", jScrollPane1);

        tokenTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Id", "Symbol", "Value"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean [] {
                false, false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        jScrollPane3.setViewportView(tokenTable);

        jTabbedPane1.addTab("Tokens", jScrollPane3);

        simbolTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Key", "Type", "Value"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean [] {
                false, false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        jScrollPane4.setViewportView(simbolTable);

        jTabbedPane1.addTab("Tabla de Simbolos", jScrollPane4);

        consoleSin.setColumns(20);
        consoleSin.setRows(5);
        jScrollPane5.setViewportView(consoleSin);

        jTabbedPane1.addTab("Estructuras Sintacticas", jScrollPane5);

        polacaText.setColumns(20);
        polacaText.setEditable(false);
        polacaText.setRows(5);
        jScrollPane6.setViewportView(polacaText);

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane6, javax.swing.GroupLayout.DEFAULT_SIZE, 765, Short.MAX_VALUE)
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane6, javax.swing.GroupLayout.DEFAULT_SIZE, 122, Short.MAX_VALUE)
        );

        jTabbedPane1.addTab("Polaca Inversa", jPanel2);

        jPanel1.add(jTabbedPane1, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 390, 770, 150));

        getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);

        jMenuBar1.setBackground(new java.awt.Color(0, 51, 51));
        jMenuBar1.setForeground(new java.awt.Color(0, 51, 51));

        jMenu1.setText("File");

        bOpen.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        bOpen.setText("Open...");
        bOpen.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bOpenActionPerformed(evt);
            }
        });
        jMenu1.add(bOpen);

        bSave.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
        bSave.setText("Save...");
        bSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bSaveActionPerformed(evt);
            }
        });
        jMenu1.add(bSave);

        bExit.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ESCAPE, 0));
        bExit.setText("Exit");
        bExit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bExitActionPerformed(evt);
            }
        });
        jMenu1.add(bExit);

        jMenuBar1.add(jMenu1);

        jMenu3.setText("Help");

        jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_H, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem1.setText("Help...");
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });
        jMenu3.add(jMenuItem1);

        jMenuItem2.setText("About...");
        jMenuItem2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem2ActionPerformed(evt);
            }
        });
        jMenu3.add(jMenuItem2);

        jMenuBar1.add(jMenu3);

        setJMenuBar(jMenuBar1);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void bExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bExitActionPerformed
        System.exit(0);
    }//GEN-LAST:event_bExitActionPerformed

    private void bCompileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bCompileActionPerformed
        try{                       
            console.setText("");
            if(!codeFile.exists()){
                codeFile = new File(defaultFilePath);            
            }           
            tokens.clear();
            FileOutputStream erasor = new FileOutputStream(codeFile);
            erasor.write(code.getText().getBytes());
            erasor.close();
            TablaSimb table = new TablaSimb();
            Lexico lex = new Lexico(new FileInputStream(codeFile),table);   
            
            PolacaInversa polaca = new PolacaInversa();
            Parser p = new Parser(lex,this,polaca);
            
            int result = p.yyparse();
            //table.printTable();
            polacaText.setText(polaca.imprimir());
            Generador g = new Generador(polaca,table);

            //g.imprimir();
            
            //table.printTable();    
          
            //Reseteo las tablas
            tablaSimModel.setRowCount(0);
            tabla.setRowCount(0);
            
            //Cargo los tokens en la tabla
            for(Token t: tokens){
                Vector aux = new Vector();
                aux.add(t.getId());
                aux.add(t.getStringId());
                aux.add(t.getKey());
                tabla.addRow(aux);
            }
                        
            //Cargo la tabla de simbolos
            Vector<Vector> vec = table.getRows();
            for(Vector<String> v: vec){
                tablaSimModel.addRow(v);
            }
                        
            
            consoleSin.setText("");
            for(String s:sintacticStructures){
                consoleSin.append("ESTRUCTURA ENCONTRADA: "+ s + '\n');
            }
            sintacticStructures.clear();
            
            Vector<String> errors = lex.getErrors(); 
            for(String s:errors){
                if(!s.equals(""))
                    appendConsole("Lexico: "+s);
            }
            if(result == 0)
                appendConsole("Compilacion exitosa.");
            else
                appendConsole("Compilacion terminada con errores.");
            
            if(g.getFatalError()){
                appendConsole("Error fatal. No se pudo generar código assembler");
            }
        
        }catch(Exception e){   
            e.printStackTrace();
            console.setText("");
            console.append("Error al compilar el codigo"+'\n');
        }
    }//GEN-LAST:event_bCompileActionPerformed

    private void bOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bOpenActionPerformed
        open();
    }//GEN-LAST:event_bOpenActionPerformed

    public void addToken(Token t){
        tokens.add(t);
    }
    
    private void open(){
        try{
            //Setea el filtro para los archivos
            HJFIlter hjfilter = new HJFIlter();
            //Setea el directorio default (Desktop del usuario)
            JFileChooser fChooser = new JFileChooser(System.getProperty("user.dire") + "/prueba.txt");
            fChooser.setMultiSelectionEnabled(false);
            fChooser.setFileFilter(hjfilter);
            fChooser.showOpenDialog(this);       
            //Obtengo el archivo seleccionado
            codeFile = fChooser.getSelectedFile();  
            //Cambio el titulo del programa
            this.setTitle("Compilador - "+codeFile.getName());
            RandomAccessFile raf = new RandomAccessFile(codeFile, "r"); 
            String codeString="";
            boolean done = false;       
            while(!done){
                String aux = raf.readLine();
                if (aux == null)
                    done = true;
                else{
                    codeString = codeString.concat(aux+'\n');                
                }
            }     
            code.setText(codeString); 
        } catch (Exception e) {              
            console.setText("");
            console.append("Error al cargar el archivo"+'\n');
        }    
    }
    
    private void save(){
        try{
            HJFIlter hjfilter = new HJFIlter();
            JFileChooser fChooser = new JFileChooser(System.getProperty("user.home") + "/Desktop/");
            fChooser.setMultiSelectionEnabled(false);
            fChooser.setFileFilter(hjfilter);
            fChooser.showSaveDialog(this);       
            File f = fChooser.getSelectedFile();
            FileOutputStream erasor = new FileOutputStream(f);
            erasor.write(code.getText().getBytes());
            erasor.close();
            codeFile = f;            
            this.setTitle("Compilador - "+codeFile.getName());
        }catch (Exception e){
            appendConsole("No se pudo guardar el archivo");
            e.printStackTrace();
        }
    }
    
    private void bSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bSaveActionPerformed
        save();
    }//GEN-LAST:event_bSaveActionPerformed

    private void bOpen2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bOpen2ActionPerformed
        open();
    }//GEN-LAST:event_bOpen2ActionPerformed

    private void bSave2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bSave2ActionPerformed
        save();
    }//GEN-LAST:event_bSave2ActionPerformed

    private void jMenuItem2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem2ActionPerformed
        About a = new About();
        a.setVisible(true);
    }//GEN-LAST:event_jMenuItem2ActionPerformed

    private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem1ActionPerformed
        Help h = new Help();
        h.setVisible(true);
    }//GEN-LAST:event_jMenuItem1ActionPerformed

    private void codeMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_codeMouseReleased
        code.repaint();
    }//GEN-LAST:event_codeMouseReleased

    public void appendConsole(String s){
        console.append(s + '\n');
    }
    
    public void addSinStruct(String s){
        sintacticStructures.add(s);
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(IDE.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(IDE.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(IDE.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(IDE.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                IDE ide = new IDE();
                ide.setVisible(true);
                ide.setResizable(false);
            }
        });
    }
    
    private File codeFile;
    private String defaultFilePath;
    private DefaultTableModel tabla;
    private DefaultTableModel tablaSimModel;
    private Vector<Token> tokens;
    private Vector<String> sintacticStructures;
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton bCompile;
    private javax.swing.JMenuItem bExit;
    private javax.swing.JMenuItem bOpen;
    private javax.swing.JButton bOpen2;
    private javax.swing.JMenuItem bSave;
    private javax.swing.JButton bSave2;
    private javax.swing.JEditorPane code;
    private javax.swing.JTextArea console;
    private javax.swing.JTextArea consoleSin;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JScrollPane jScrollPane5;
    private javax.swing.JScrollPane jScrollPane6;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JTextArea polacaText;
    private javax.swing.JTable simbolTable;
    private javax.swing.JTable tokenTable;
    // End of variables declaration//GEN-END:variables

    
    private void loadDefaultCode() {
        try{
            codeFile = new File(defaultFilePath);
            RandomAccessFile raf = new RandomAccessFile(codeFile, "r"); 
            String codeString="";
            boolean done = false;       
            while(!done){
                String aux = raf.readLine();
                if (aux == null)
                    done = true;
                else{
                    codeString = codeString.concat(aux+'\n');                
                }
            }     
            code.setText(codeString); 
            raf.close();
            this.setTitle("Compilador - "+codeFile.getName());
        }catch(Exception e){
            appendConsole("Default code not found. Open a new code or create one");
        }
    }
}
